架构设计-复杂度是不灭的
作者简介:姚钢强,具有丰富的技术架构和业务架构经验;2013 - 2019 在知乎工作,完整经历了知乎从内部注册到上千万 DAU 的过程;2019 年加入猿辅导,担任斑马事业部首席架构师的职务,主要负责工程实践的改善与架构的优化;参与重要业务与技术架构方案的评审;目前微服务架构趋向合理,数量大幅削减,依赖逐渐清晰;也逐步建立了以 Metrics 驱动的 DevOps 文化。
@陶文 的 《复杂度是不灭的,只会转移,难道一切都是徒劳的吗?》[1] 提到了 《Complexity Has to Live Somewhere》[2] 这篇文章,这篇文章超级棒,阐述了架构设计的核心。为了透彻理解文中的观点,所以逐字翻译了一下。翻译水平有限,肯定存在疏漏,多多包涵。
与复杂度的斗争是软件开发的一个永恒的主题,我一次又一次地看到它反复出现,并且不断在各个层面上看到有关的争论:到底应该在函数和方法中进行多少注释?理想的抽象是怎样的?一个框架何时开始拥有了「过多的魔法」?什么时候组织中有太多语言?
我们试图摆脱复杂度,控制它,寻求简单性。我认为以这种思考方式来寻求问题的解决方案是错误的。因为复杂度必须存在于某个地方,是不灭的。
Resilience Engineering 教给我一个来自控制论的 "必要多样性 "概念:「只有复杂度才能处理复杂度。」
在处理构建工具时,一些事情变得显而易见:
如果你让构建工具变得简单,它就不能处理所有存在的奇怪的边缘情况。
如果你想处理奇怪的边缘情况,就需要偏离你想建立的任何规范。
如果你想让通用默认值易于使用,那么通用默认值的规则必须在工具和用户之间共享,而用户则要改造自己的系统来适应工具。
如果你允许自主配置或编写脚本,你就给了用户一种方法来指定必须共享的规则,以便工具适合他们的系统。
如果你想保持工具的简单性,你就必须强迫你的用户只在适合这种简单性的参数范围内玩耍。
如果用户的用例不能很好地与你的工具简单性相匹配,他们就会在你的工具周围建立垫片(周围的小工具)来实现他们的目标。
这是无法避免的。复杂度必须存在于某个地方。无论您是否意识到,它始终是人们解决问题时需要注意到的。
不幸的是,如果我们做到了列表的最后一点(我们总是以某种方式这样做),垫片就会成为整体工具的一部分。复杂度并不会消失。这部分复杂度是每个人必须要学习的,用户会需要适应它。
他们尝试绕过复杂度时,看到了两个冲突的概念(译者注:类似 ORM 中的 O 和 R 的概念)之间的不匹配。这种必要的复杂度可能会转移 -- 回到工具(或新工具)-- 或者通过重新构建事物来消除。每一个这样的变化都需要付出更多的努力和调整,让人们看到复杂度,理解它,并解决它。但是在某些情况下,这种变化不会使事情简化,而是会在人们的各种假设之间产生新的不匹配,从而使事情复杂化,这就需要新的垫片。必然复杂度时间久了之后,就变成了偶然复杂度。它无法避免,而且它一直在变化。复杂度必须存在于某个地方。
在 《The Design of Everyday Things》 中,Don Norman 提到了“头脑中的知识”和“世界中的知识”的概念(类似的概念更学术话的出现在了 Roesler & Woods 的《Designing for Expertise》)。头脑中的知识是你知道的、你学到的、你记忆中的东西。世界上的知识是其他的一切:写下来的信息,设计中的线索(你通过看它的符号知道电源按钮,你知道它可以被按下,因为它看起来像一个按钮)。一件棘手的事情是,对世界上的知识的解释既有文化上的,也有上下文上的,并且依赖于头脑中的知识(你知道电源按钮可以被按下,因为你知道按钮首先是什么)。
在某些方面,专业知识是在你头脑中可以使你能更好地了解世界的知识。
将精力放在发现阅读和解释一段特定的代码有多 "简单"是我们在软件设计中的一个常见的陷阱。专注于简单性是充满危险的,因为复杂度无法消除:它只能被转移。如果你把它从你的代码中移出来,它去了哪里呢?
当我们设计 Rebar3 时,我们觉得这个工具可以很简单。其简单的条件是,你对 Erlang/OTP 项目的预期结构有一个基本的了解。只要你遵循这些规则,项目就会运转的很好。我们把一些复杂的东西外化到更广泛的生态系统中。这些规则总是需要学习的(我们是这么认为的),但现在的工具取决于对它们的理解。在为了解规则的人简化工具的使用时,我们使那些仍在学习规则的人更难使用。在其他生态系统中用于其他目的的工具都在做类似的权衡。
这个陷阱在软件架构中是隐蔽的。当我们采用微服务之类的东西时,我们会尽量使每个服务都变得简单。但是除非你能够使你的真实应用可以强制进入简单的状态,否则复杂度仍然必须去某个地方。如果它不在各个微服务中,那么它在哪里(译者注:使用微服务的人仍然要知道规则是什么,如何使之简单)?
复杂度必须存在于某个地方。如果你幸运的话,复杂度在定义明确的地方。在你认为有点复杂的代码中,在支持代码的文档中,在工程师的培训课程中。你给了复杂度一个地方,而不是试图隐藏它。你创造方法来管理它。你知道当你需要它的时候,该去哪里找它。如果不走运,你只是试图假装复杂度可以完全消除,那么它在这个世界上就没有地方可去。但它仍然会一直存在于这个世界。
由于无处可去,复杂度不得不在你的系统中到处游荡,包括在你的代码中和人们的头脑中。随着人的转移和离开,我们对它的理解逐渐减弱。
复杂度必须存在于某个地方,它是不会消失的。如果你接受它,给它应有的位置,在设计你的系统和组织时知道它的存在,并专注于适应它,它可能就会成为帮助软件架构设计的一种力量。
原文地址:
文中链接:
[1] https://zhuanlan.zhihu.com/p/138145081
[2] https://ferd.ca/complexity-has-to-live-somewhere.html
技术原创及架构实践文章,欢迎通过公众号菜单「联系我们」进行投稿。